---
title: "External (Bind to Any JS Library)"
description: "The external keyword"
canonical: "/docs/manual/external"
section: "JavaScript Interop"
order: 3
---

# External (Bind to Any JS Library)

`external` is the primary ReScript feature for bringing in and using JavaScript values.

`external` is like a let binding, but:

- The right side of `=` isn't a value; it's the name of the JS value you're referring to.
- The type for the binding is mandatory, since we need to know what the type of that JS value is.
- Can only exist at the top level of a file or module.

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
@val external setTimeout: (unit => unit, int) => float = "setTimeout"
```

```js
// Empty output
```

</CodeTab>

There are several kinds of `external`s, differentiated and/or augmented through the [attribute](./attribute.mdx) they carry. This page deals with the general, shared mechanism behind most `external`s. The different `external`s are documented in their respective pages later. A few notable ones:

- `@val`, `@scope`: [bind to global JS values](./bind-to-global-js-values.mdx).
- `@module`: [bind to JS imported/exported values](./import-from-export-to-js.mdx).
- `@send`: [bind to JS methods](./bind-to-js-function.mdx).

You can also use our [Syntax Lookup](../../syntax-lookup/) tool to find them.

Related: See our [interop cheatsheet](./interop-cheatsheet.mdx) for an overview.

## Usage

Once declared, you can use an `external` as a normal value, just like a let binding.

## Tips & Tricks

`external` + ReScript objects are a wonderful combination for quick prototyping. Check the JS output tab:

<CodeTab labels={["ReScript", "JS Output"]}>

```res example
// The type of document is just some random type 'a
// that we won't bother to specify
@val external document: 'a = "document"

// call a method
document["addEventListener"]("mouseup", _event => {
  Console.log("clicked!")
})

// get a property
let loc = document["location"]

// set a property
document["location"]["href"] = "rescript-lang.org"
```

```js
document.addEventListener("mouseup", function (_event) {
  console.log("clicked!");
});

var loc = document.location;

document.location.href = "rescript-lang.org";
```

</CodeTab>

We've specified `document`'s type as `'a`, aka a placeholder type that's polymorphic. Any value can be passed there, so you're not getting much type safety (except the inferences at various call sites). However, this is excellent for quickly getting started using a JavaScript library in ReScript **without needing the equivalent of a repository of typed bindings** like TypeScript's `DefinitelyTyped` repo.

However, if you want to more rigidly bind to the JavaScript library you want, keep reading the next few interop pages.

## Performance & Output Readability

`external`s declarations are inlined into their callers during compilation, **and completely disappear from the JS output**. This means any time you use one, you can be sure that you're not incurring extra JavaScript \<-> ReScript conversion cost.

Additionally, no extra ReScript-specific runtime is better for output readability.

> **Note:** do also use `external`s and the `@blabla` attributes in the interface files. Otherwise the inlining won't happen.

## Design Decisions

ReScript takes interoperating with existing code very seriously. Our type system has very strong guarantees. However, such strong feature also means that, without a great interop system, it'd be very hard to gradually convert a codebase over to ReScript. Fortunately, our interop are comprehensive and cooperate very well with most existing JavaScript code.

The combination of a sound type system + great interop means that we get the benefits of a traditional gradual type system regarding incremental codebase coverage & conversion, without the downside of such gradual type system: complex features to support existing patterns, slow analysis, diminishing return in terms of type coverage, etc.
